/*
 * win32.cpp
 *
 *  Created on: 2012-8-30
 *      Author: yangentao@gmail.com
 */

#include <windows.h>
#include <CommDlg.h>
#include "win32.h"
#include "ole/DataObjectImpl.h"

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#pragma comment(lib, "comctl32.lib")

namespace yet{

static DWORD MainThreadID = GetCurrentThreadId();


bool isKeyDown(int key) {
	return (::GetKeyState(key) & 0x80000000) != 0;
}

long getTimeTick(){
	return ::GetTickCount();
}

//IsClipboardFormatAvailable/OpenClipboard/GetClipboardData
String getClipboardText() {
	String s;
	IDataObject* data = 0;
	if (::OleGetClipboard(&data) != S_OK ) {
		return s;
	}
	FORMATETC formatEtc = { 0 };
	formatEtc.cfFormat = CF_TEXT; //TODO CF_UNICODETEXT
	formatEtc.ptd = 0;
	formatEtc.dwAspect = DVASPECT_CONTENT;
	formatEtc.lindex = -1;
	formatEtc.tymed = TYMED_HGLOBAL;

	STGMEDIUM store;
	if (data->GetData(&formatEtc, &store) == S_OK ) {
		char* buf = (char*) GlobalLock(store.hGlobal);
		s.copyFrom(buf, strlen(buf));
		GlobalUnlock(store.hGlobal);
		ReleaseStgMedium(&store);
	} else {
		//TODO Unicode
	}

	data->Release();

	return s;
}

bool setClipboardText(String s, bool unicode) {
	//TODO unicode
	IDataObject* pDataObject = CreateDataObject(s.buffer(), s.length());
	if (pDataObject) {
		OleSetClipboard(pDataObject);
		OleFlushClipboard();
		pDataObject->Release();
		return true;
	}
	return false;
}

HGLOBAL DupMem(HGLOBAL hMem) {
	void* pMem = GlobalLock(hMem);
	int size = GlobalSize(hMem);
	HGLOBAL h = GlobalAlloc(GMEM_FIXED, size);
	if (h) {
		void* p = GlobalLock(h);
		memmove(p, pMem, size);
		GlobalUnlock(h);
	}
	GlobalUnlock(hMem);
	return h;
}

WString getOpenFileName(){
	WString ws;
	OPENFILENAME of = {0};
	of.lStructSize = sizeof(of);

	if(GetOpenFileName(&of)){
		return ws;
	}
	return WString();
}

bool isMainThread(){
	return isMainThread(GetCurrentThreadId());
}
bool isMainThread(DWORD threadID){
	return MainThreadID == threadID;
}

string formatMessage(DWORD errCode) {
	char* buffer;
	DWORD n = ::FormatMessageA(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
			errCode, 0, (LPSTR) &buffer, 0, NULL);
	string msg;
	if (n) {
		msg = buffer;
	}
	LocalFree(buffer);
	return msg;
}

wstring formatMessageW(DWORD errCode) {
	wchar_t* buffer;
	DWORD n = ::FormatMessageW(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
			errCode, 0, (LPWSTR) &buffer, 0, NULL);
	wstring msg;
	if (n) {
		msg = buffer;
	}
	LocalFree(buffer);
	return msg;
}
}
